﻿var drawOnDemand = true;
// ENGINE
RdEngine = function (container, opts) {
    if (opts == undefined)
        opts = {};
    var me = this;
    var stage = new Kinetic.Stage({
        container: container,
        width: parseInt($('#' + container).css('width').replace('px', '')),
        height: parseInt($('#' + container).css('height').replace('px', ''))
    });

    var layer = new Kinetic.Layer();
    var tooltipLayer = new Kinetic.Layer();
    stage.add(layer);
    stage.add(tooltipLayer);
    var tooltip = new Kinetic.Text({
        text: "",
        fontFamily: "Calibri",
        fontSize: 12,
        padding: 5,
        textFill: "white",
        fill: "black",
        alpha: 0.75,
        visible: false
    });
    tooltipLayer.add(tooltip);

    var creatingconnector = undefined;
    var selectedElement = undefined;

    var nodes = [];
    var connectors = [];
    var pendingCreatedElements = [];

    function regNodeEvent(node) {
        node.connectCircle.on('mousedown', function (evt) {
            evt.cancelBubble = true;
            creatingconnector = new ConnectorControl(
            {
                x1: evt.offsetX,
                y1: evt.offsetY,
                x2: evt.offsetX,
                y2: evt.offsetY,
                layer: layer,
                creating: true,
                node1: node
            });
        });
        node.group.on('mouseup', function (evt) {
            if (creatingconnector != undefined) {
                evt.cancelBubble = true;
            }

            var cancelEvent = false;

            if (creatingconnector != undefined && node != creatingconnector.node1) {
                cancelEvent = true;
                creatingconnector.node2 = node;
                me.createConnector({ node1: creatingconnector.node1, node2: creatingconnector.node2, data: { hash: Utils.guid() }, clone: creatingconnector });
                creatingconnector.dispose();
                creatingconnector = undefined;
            }
            if (creatingconnector != undefined && node == creatingconnector.node1) {
                releaseCreatingConnector();
            }

            if (me.onElementMouseUp != undefined && !cancelEvent)
                me.onElementMouseUp(node);

            layer.draw();

        });

        node.group.on('dragmove dragstart dragend', function (evt) {
            for (var i = 0; i < node.connectors.length; i++) {
                node.connectors[i].updatePositionByNodes();
            }

            evt.cancelBubble = true;
        });
    }

    function regElementEvent(element) {

        element.group.on('click', function (evt) {
            releaseSelectedObj();
            element.setSelected(true);
            selectedElement = element;
            selectedElement.layer.draw();
            evt.cancelBubble = true;
        });

        element.group.on('mousemove', function () {
            var mousePos = stage.getMousePosition();
            tooltip.setPosition(mousePos.x + 10, mousePos.y + 5);
            tooltip.setText(element.text);
            tooltip.show();
            tooltipLayer.draw();
        });

        element.group.on("mouseout", function () {
            tooltip.hide();
            tooltipLayer.draw();
        });
    }

    function releaseSelectedObj() {
        if (selectedElement != undefined) {
            selectedElement.setSelected(false);
            selectedElement.layer.draw();
        }
    }

    $(layer.parent.container).mousemove(function (evt) {
        if (creatingconnector != undefined) {
            var cPos = creatingconnector.node1.connectCircle.getAbsolutePosition();
            var points = GeometryHelper.getJoinedPointsOfCircleAndLine1(
            cPos.x,
            cPos.y,
            creatingconnector.node1.connectCircle.getRadius(),
            evt.offsetX, evt.offsetY);
            creatingconnector.setPos1(points[0], points[1]);

            creatingconnector.setPos2(evt.offsetX, evt.offsetY);
        }
    });

    $(layer.parent.container).mouseup(function (evt) {
        if (creatingconnector != undefined) {
            releaseCreatingConnector();
            return;
        }

        releaseSelectedObj();
    });

    $(document).mouseup(function (evt) {
        if (selectedElement != undefined)
            releaseSelectedObj();
    });

    var keyupHandle = function (evt) {
        if (selectedElement == undefined)
            return;

        var code = (evt.keyCode ? evt.keyCode : evt.which);

        if (code == 46) {
            var todel = selectedElement;
            releaseSelectedObj();

            if (todel.typeName == 'NodeControl')
                me.removeNode(todel);
            if (todel.typeName == 'ConnectorControl')
                me.removeConnector(todel);

            layer.draw();
        }
    }

    $(document).bind('keyup', keyupHandle);

    this.destroy = function () {
        $(document).unbind('keyup', keyupHandle);
    }


    function releaseCreatingConnector() {
        if (creatingconnector != undefined) {
            layer.remove(creatingconnector.group);
            creatingconnector = undefined;

            layer.draw();
        }
    }

    this.getLayer = function () {
        return layer;
    }

    this.getNodes = function () {
        return nodes;
    }

    // events
    this.onElementCreating = opts.onElementCreating;
    this.onElementMouseUp = opts.onElementMouseUp;
    this.onElementRemoving = opts.onElementRemoving;

    this.addNode = function (options) {
        var node = new NodeControl({ x: options.x,
            y: options.y, layer: layer, draggable: true, text: options.text, model: options.data
        });

        nodes.push(node);
        layer.add(node.Me);

        regElementEvent(node);
        regNodeEvent(node);

        return node;
    }

    this.createNode = function (options) {
        var node = me.addNode(options);
        elementCreating(node);
    }

    this.createConnector = function (options) {
        var connector = me.addConnector(options);
        elementCreating(connector);
    }



    this.addConnector = function (options) {
        var connector;
        if (options.clone == undefined)
            connector = new ConnectorControl({ node1: options.node1, node2: options.node2, layer: layer, model: options.data });
        else
            connector = new ConnectorControl({ node1: options.clone.node1, node2: options.clone.node2, layer: layer, model: options.data });

        connector.updatePositionByNodes();
        connector.node1.connectors.push(connector);
        connector.node2.connectors.push(connector);
        regElementEvent(connector);
        connectors.push(connector);
        layer.add(connector.Me);

        return connector;
    }



    function elementCreating(element) {
        if (me.onElementCreating == undefined)
            return;
        element.pendingCreateHash = Utils.guid();
        pendingCreatedElements.push(element);
        me.onElementCreating(
        {
            element: element,
            success: function (evt) {
                pendingCreatedElements.remove(element);
            },
            fail: function (evt) {
                pendingCreatedElements.remove(element);
            }
        });
    }

    function elementRemoving(element) {
        if (me.onElementRemoving == undefined)
            return;
        me.onElementRemoving(
        {
            element: element,
            success: function (evt) { },
            fail: function (evt) { }
        });

    }


    this.removeNode = function (node) {
        if (me.onElementRemoving == undefined) {
            removeUiNode(node);
            return;
        }

        me.onElementRemoving(
        {
            element: node,
            success: function (evt) { removeUiNode(node); },
            fail: function (evt) { }
        });
    }

    function removeUiNode(node) {
        node.dispose();
        nodes.remove(node);

        for (var i = 0; i < node.connectors.length; i++) {
            removeUiConnector(node.connectors[i]);
        }

        layer.draw();
    }

    this.getNodes = function () {
        return nodes;
    }

    this.removeConnector = function (connector) {
        removeUiConnector(connector);
        connector.node1.connectors.remove(connector);
        connector.node2.connectors.remove(connector);

        elementRemoving(connector);
    }

    function removeUiConnector(connector) {
        connector.dispose();
        connectors.remove(connector);
    }

    var text = new Kinetic.Text({
        x: 10,
        y: 10,
        text: 'RD',
        fontSize: 10,
        fontFamily: "Tahoma",
        fontStyle: 'bold',
        textFill: "red",
        align: "left",
        verticalAlign: "middle"
    });
    layer.add(text);

    this.setText = function (txt) {
        text.attrs.text = txt;
        layer.draw();
    }

    this.draw = function () {
        layer.draw();
    }

    layer.draw();
}